package chapter1;

import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import java.util.Queue;
import java.util.concurrent.ArrayBlockingQueue;

/**
 * @author caiya
 * @date 2020/3/12 20:24
 */
@Slf4j
public class WaitNotifyTest {
    private static final Object obj = new Object();

    public static void main(String[] args) {
        /**
         * 1、wait和notify介绍
         *      wait：会导致当前线程被阻塞挂起，并释放其wait关联的共享对象资源锁，其它资源锁并不会释放
         *      notify：唤醒因调用当前对象的wait方法被挂起线程（只会唤醒一个，具体看CPU调度）
         */

        Queue<Double> queue = new ArrayBlockingQueue<Double>(200);

        ProducerThread producerThread = new ProducerThread(queue);
        ConsumerThread consumerThread = new ConsumerThread(queue);

        new Thread(producerThread).start();

        new Thread(consumerThread).start();

    }

    /**
     * 生产者线程
     */
    @AllArgsConstructor
    static class ProducerThread implements Runnable{
        private Queue<Double> queue;
        private static final int MAX_SIZE = 100;

        @Override
        public void run() {
            while (true) {
                synchronized (queue) {
                    while (queue.size() >= MAX_SIZE) {
                        try {
                            queue.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    queue.add(Math.random());
                    queue.notify();
                }
            }
        }
    }

    /**
     * 消费线程
     */
    @AllArgsConstructor
    static class ConsumerThread implements Runnable {
        private Queue<Double> queue;

        @Override
        public void run() {
            while (true) {
                synchronized (queue) {
                    while (queue.size() == 0) {
                        try {
                            queue.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    queue.peek();
                    queue.notify();
                }
            }
        }
    }
}